home *** CD-ROM | disk | FTP | other *** search
Oberon Document | 1996-01-05 | 6.1 KB | 156 lines | [oODC/obnF] |
- Documents.StdDocumentDesc
- Documents.DocumentDesc
- Containers.ViewDesc
- Views.ViewDesc
- Stores.StoreDesc
- Documents.ModelDesc
- Containers.ModelDesc
- Models.ModelDesc
- Stores.ElemDesc
- TextViews.StdViewDesc
- TextViews.ViewDesc
- TextModels.StdModelDesc
- TextModels.ModelDesc
- TextModels.AttributesDesc
- Helvetica
- Helvetica
- Helvetica
- MODULE ObxMMerge;
- (* note that as in the other sample programs, no error handling is performed *)
- IMPORT Files, Dialog, Views, TextModels, TextViews, TextControllers;
- CONST tab = 09X;
- TYPE
- Field = POINTER TO RECORD
- prev: Field; (* field list is sorted in reverse order *)
- name: ARRAY 24 OF CHAR; (* name of placeholder *)
- tmplFrom, tmplTo: LONGINT; (* character range used by placeholder in template *)
- index: INTEGER; (* column index of this field *)
- dataFrom, dataTo: LONGINT (* character range used by actual data in database *)
- END;
- PROCEDURE TmplFields (t: TextModels.Model): Field;
- (* returns a list of placeholder fields, in reverse order *)
- (* each field defines a text range and name of a placeholder *)
- (* the placeholder has the form "...<NameOfPlaceholder>..." *)
- VAR l, f: Field; r: TextModels.Reader; ch: CHAR; i: INTEGER;
- BEGIN
- l := NIL; r := t.NewReader(NIL); r.SetPos(0); r.ReadChar(ch);
- WHILE ~r.eot DO
- IF ch = "<" THEN
- NEW(f); f.tmplFrom := r.Pos() - 1;
- r.ReadChar(ch); i := 0;
- WHILE ch # ">" DO
- f.name[i] := ch; INC(i);
- r.ReadChar(ch)
- END;
- f.name[i] := 0X; f.tmplTo := r.Pos();
- f.dataFrom := -1; f.dataTo := -1;
- f.prev := l; l := f
- END;
- r.ReadChar(ch)
- END;
- RETURN l
- END TmplFields;
- PROCEDURE ThisDatabase (): TextModels.Model;
- VAR loc: Files.Locator; name: Files.Name; file: Files.File; v: Views.View;
- t: TextModels.Model;
- BEGIN
- t := NIL;
- Dialog.GetIntSpec("", loc, name);
- IF loc # NIL THEN
- v := Views.OldView(loc, name);
- IF (v # NIL) & (v IS TextViews.View) THEN
- t := v(TextViews.View).ThisModel()
- END
- END;
- RETURN t
- END ThisDatabase;
- PROCEDURE MergeFields (f: Field; t: TextModels.Model);
- (* determine every template field's index in the data text's row of fields *)
- VAR r: TextModels.Reader; index, i: INTEGER; ch: CHAR;
- BEGIN
- r := t.NewReader(NIL);
- WHILE f # NIL DO (* iterate over all fields in the template *)
- f.index := -1;
- r.SetPos(0); index := 0; ch := tab;
- WHILE (ch = tab) & (f.index = -1) DO (* compare names of the fields *)
- REPEAT r.ReadChar(ch) UNTIL ch >= " ";
- i := 0; WHILE ch = f.name[i] DO r.ReadChar(ch); INC(i) END;
- IF (ch < " ") & (f.name[i] = 0X) THEN (* names match *)
- f.index := index
- ELSE (* no match; proceed to next data field *)
- WHILE ch >= " " DO r.ReadChar(ch) END
- END;
- INC(index)
- END;
- f := f.prev
- END
- END MergeFields;
- PROCEDURE ReadTuple (f: Field; r: TextModels.Reader);
- (* read tuple in data, and assign ranges to corresponding fields *)
- VAR index: INTEGER; from, to: LONGINT; ch: CHAR; g: Field;
- BEGIN
- index := 0; ch := tab;
- WHILE ch = tab DO
- REPEAT r.ReadChar(ch) UNTIL (ch = 0X) OR (ch >= " ");
- from := r.Pos() - 1;
- WHILE ch >= " " DO r.ReadChar(ch) END;
- to := r.Pos(); IF ~r.eot THEN DEC(to) END;
- g := f;
- WHILE g # NIL DO
- IF g.index = index THEN g.dataFrom := from; g.dataTo := to END;
- g := g.prev
- END;
- INC(index)
- END
- END ReadTuple;
- PROCEDURE AppendInstance (f: Field; data, tmpl, out: TextModels.Model);
- VAR start, from: LONGINT; r: TextModels.Reader; attr: TextModels.Attributes;
- BEGIN
- start := out.Length();
- r := out.NewReader(NIL);
- out.CopyFrom(start, tmpl, 0, tmpl.Length()); (* append new copy of template *)
- WHILE f # NIL DO (* substitute placeholders, from end to beginning of template *)
- from := start + f.tmplFrom;
- r.SetPos(from); r.ReadRun(attr); (* save attributes *)
- out.Delete(from, from + f.tmplTo - f.tmplFrom); (* delete placeholder *)
- out.CopyFrom(from, data, f.dataFrom, f.dataTo); (* insert actual data *)
- out.SetAttr(from, from + f.dataTo - f.dataFrom, attr); (* set attributes *)
- f := f.prev
- END
- END AppendInstance;
- PROCEDURE Merge*;
- VAR c: TextControllers.Controller; tmpl, data, out: TextModels.Model;
- tmplFields: Field; r: TextModels.Reader; v: TextViews.View;
- BEGIN
- c := TextControllers.Focus();
- IF c # NIL THEN
- tmpl := c.text; (* text template used for mail merge *)
- tmplFields := TmplFields(tmpl); (* determine fields in template *)
- data := ThisDatabase(); (* get text database for mail merge *)
- IF data # NIL THEN
- MergeFields(tmplFields, data); (* determine every template field's column in database *)
- out := TextModels.dir.New(); (* create output text *)
- r := data.NewReader(NIL); r.SetPos(0);
- ReadTuple(tmplFields, r); (* skip meta data *)
- REPEAT
- ReadTuple(tmplFields, r); (* read next data row *)
- AppendInstance(tmplFields, data, tmpl, out) (* append new instance of template *)
- UNTIL r.eot;
- v := TextViews.dir.New(out);
- Views.OpenView(v) (* open text view in window *)
- END
- END
- END Merge;
- END ObxMMerge.
- TextControllers.StdCtrlDesc
- TextControllers.ControllerDesc
- Containers.ControllerDesc
- Controllers.ControllerDesc
- TextRulers.StdRulerDesc
- TextRulers.RulerDesc
- TextRulers.StdStyleDesc
- TextRulers.StyleDesc
- TextRulers.AttributesDesc
- Helvetica
- Documents.ControllerDesc
-